package com.isoft.c2team3service2.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isoft.c2team3service2.bean.ResponseData;
import com.isoft.c2team3service2.dto.ArtistRegisterDTO;
import com.isoft.c2team3service2.entity.*;
import com.isoft.c2team3service2.mapper.*;
import com.isoft.c2team3service2.service.UserService;
import com.isoft.c2team3service2.util.PwdSaltUtil;

import com.isoft.c2team3service2.util.UserHolder;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.isoft.c2team3service2.util.PwdSaltUtil.validPassword;
import static com.isoft.c2team3service2.util.RedisConstants.USER_CODE_KEY;
import static com.isoft.c2team3service2.util.RedisConstants.USER_LOGIN_KEY;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ArtistMapper artistMapper;

    @Autowired
    private HeadMapper headMapper;

    @Autowired
    private  StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PersonMapper personMapper;

    @Autowired
    private FileServiceImp fileServiceImp;

    @Autowired
    private UserRoleMapper userRoleMapper;

    //邮箱验证
    @Override
    public String repeatEmail(String email) {
        if(StrUtil.isEmpty(email)){
            return null;
        }
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        QueryWrapper<User> email1 = queryWrapper.eq("email", email);

        User user = userMapper.selectOne(email1);
        if(user == null){
            return null;
        }else{
            return  "success";
        }
    }

    //登录
    @Override
    public ResponseData<UserDTO> login(String email, String password, HttpServletResponse response)  {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        QueryWrapper<User> account = queryWrapper.eq("email", email);
        User user = userMapper.selectOne(account);
        if (user == null) {
            return new ResponseData<>(5002, "用户不存在", null);
        }

        String passwordInDb = user.getPassword();
        String salt = user.getSalt();

        boolean r;
        try {
            r = validPassword(password, salt, passwordInDb);
            if (r) {
                QueryWrapper<Person> p = new QueryWrapper<>();
                p.eq("email", email);
                Person person = personMapper.selectOne(p);
                String username = person.getUsername();
                String nick_name = person.getNickName();
                String isArtist = person.getIsArtist();

                UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
                userDTO.setNickName(nick_name); // 关键：手动设置昵称到UserDTO
                userDTO.setUsername(username);
                userDTO.setIsArtist(isArtist);

                Map<String, Object> map = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                        CopyOptions.create()
                                .setIgnoreNullValue(true)
                                .setFieldValueEditor((fieldName, fieldValue) ->
                                        fieldValue == null ? "" : fieldValue.toString())
                );

                String token = UUID.randomUUID().toString(true);
                map.put("Token", token);
                map.put("username", username);
                map.put("nickName", nick_name);

                stringRedisTemplate.opsForHash().putAll(USER_LOGIN_KEY + token, map);
                stringRedisTemplate.expire(USER_LOGIN_KEY + token, 60 , TimeUnit.MINUTES);

                // 设置响应头
                response.setHeader("Authorization", token);
                // 将完整的UserDTO存入ThreadLocal
                UserHolder.saveUser(userDTO); // 使用正确的方法名
                return new ResponseData<>(200, "登录成功", userDTO);
            } else {
                return new ResponseData<>(5003, "用户密码错误，再仔细检查一下", null);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);

        }
    }
    //修改密码
    @Override
    public boolean updatePassword(String email, String password) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if(email == null){
            return false;
        }
        if(password == null||password.isEmpty()){
            return false;
        }

        String salt = PwdSaltUtil.getSalt();
        String encryptedPassword = PwdSaltUtil.getEncryptedPwd(password, salt);

        return userMapper.updatePassword(email, encryptedPassword , salt)>0;
    }

    //注册
    @Override
    @Transactional
    public Map<String, Object> register(String email, String code, String password , Integer roleId) {
        Map<String, Object> result = new HashMap<>();

        String s = stringRedisTemplate.opsForValue().get(USER_CODE_KEY + email);

        // 验证码是否过期
        if (s == null) {
            result.put("fail", false);
            result.put("message", "验证码已过期，请重新获取");
            return result;
        }

        // 验证验证码是否正确
        if (!s.equals(code)) {
            result.put("success", false);
            result.put("message", "验证码错误");
            return result;
        }

        // 验证通过，执行注册逻辑（如保存用户到数据库）
        try {
            addUser(email,password,roleId);// 示例：调用用户服务注册
            result.put("success", true);
            result.put("message", "注册成功");
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "注册失败：" + e.getMessage());
        } finally {
            stringRedisTemplate.delete(USER_CODE_KEY + email);
        }

        return result;
    }

    /**
     * 艺人注册核心逻辑（事务保证三表一致性）
     */
    @Override
    @Transactional(rollbackFor = {Exception.class, RuntimeException.class}) // 事务注解：任一表插入失败则回滚
    public Map<String, Object> artistRegister(ArtistRegisterDTO dto) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        Map<String, Object> result = new HashMap<>();
        // 1. 统一处理邮箱：与EmailServiceImp一致（trim+toLowerCase）
        String processedEmail = dto.getEmail().trim();
        String clientCode = dto.getCode(); // 客户端传递的验证码
        String redisKey = USER_CODE_KEY + processedEmail;

        // 2. 打印调试日志：便于对比客户端code和Redis code
        log.info("艺人注册验证码校验：processedEmail={}, 客户端code={}, Redis键={}",
                processedEmail, clientCode, redisKey);

        // 3. 验证码校验
        String redisCode = stringRedisTemplate.opsForValue().get(redisKey);
        if (redisCode == null) {
            result.put("success", false);
            result.put("message", "验证码已过期，请重新获取");
            return result;
        }
        // 注意：若客户端传递的code有空格，也需trim（避免用户输入时误加空格）
        if (!redisCode.equals(clientCode.trim())) {
            log.error("验证码不匹配：Redis code={}, 客户端code（trim后）={}", redisCode, clientCode.trim());
            result.put("success", false);
            result.put("message", "验证码错误");
            return result;
        }

        // 4. 校验邮箱是否已注册（复用repeatEmail逻辑）
        QueryWrapper<User> userQuery = new QueryWrapper<>();
        userQuery.eq("email", processedEmail);
        if (userMapper.selectOne(userQuery) != null) {
            result.put("success", false);
            result.put("message", "该邮箱已被注册");
            return result;
        }

        // 5. 生成密码盐值并加密密码
        String salt = PwdSaltUtil.getSalt();
        String encryptedPassword = PwdSaltUtil.getEncryptedPwd(dto.getPassword(), salt);

        // 6. 插入tb_login表（User）：用户类型设为1（艺人）
        User user = new User();
        user.setEmail(processedEmail);
        user.setPassword(encryptedPassword);
        user.setSalt(salt);
        user.setUserType(1); // 关键：艺人标识
        int userInsert = userMapper.insert(user);
        if (userInsert <= 0) {
            throw new RuntimeException("用户表插入失败");
        }
        Integer userId = user.getId(); // 获取自增的用户ID

        // 7. 插入tb_person表（Person）：isArtist设为"1"
        Person person = new Person();
        person.setUsername(dto.getUsername());
        person.setNickName(dto.getNickName());
        person.setBirthdate(dto.getBirthdate());
        person.setPhonenumber(dto.getPhonenumber());
        person.setEmail(processedEmail);
        person.setIsArtist("1"); // 标识为艺人
        person.setBackground("default_background.png"); // 默认背景图
        int personInsert = personMapper.insert(person);
        if (personInsert <= 0) {
            throw new RuntimeException("会员表插入失败");
        }

        // 8. 插入artist表（Artist）：关联用户ID
        Artist artist = new Artist();
        artist.setName(dto.getArtistName());
        artist.setBirthDate(dto.getArtistBirthDate());
        artist.setGender(dto.getGender());
        artist.setNationality(dto.getNationality());
        artist.setAchievements(dto.getAchievements());
        artist.setWorks(dto.getWorks());
        artist.setUserId(userId); // 关联tb_login的user.id
        int artistInsert = artistMapper.insert(artist);  // 使用artistMapper
        if (artistInsert <= 0) {
            throw new RuntimeException("艺人表插入失败");
        }

        // 9. 更新User表的artistId（关联艺人ID）
        user.setArtistId(artist.getId());
        userMapper.updateById(user);

        // 10. 注册成功：删除Redis验证码，返回结果
        stringRedisTemplate.delete(USER_CODE_KEY + processedEmail);
        result.put("success", true);
        result.put("message", "艺人注册成功");
        result.put("email", processedEmail);
        result.put("userType", 1); // 告知前端是艺人用户

        return result;
    }

    @Override
    public String upLodeId(Integer userId) {
        if (userId == null) {
            return null;
        }
        return headMapper.selectHead(userId);
    }

    //上传头像
    @Override
    public String upLode(String email) {
        if (email == null || email.isEmpty()) {
            return null;
        }
        return headMapper.upLode(email);
    }

    //上传背景图
    @Override
    public String upload(MultipartFile file) {
        UserDTO user = UserHolder.getUser();
        Integer id = user.getId();
        return fileServiceImp.background("background",file,id);
    }

    @Transactional
    public boolean addUser(String email, String password , Integer roleId) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        if(email == null||password == null){
            return false;
        }

        String salt = PwdSaltUtil.getSalt();
        String encryptedPassword = PwdSaltUtil.getEncryptedPwd(password, salt);

        return userMapper.addUser(email, encryptedPassword, salt) > 0;
    }

}
